-define(DGIOT_MODBUS_TCP_DTU, dgiot_modbus_tcp_dtu_ets).
-record(state, {
    id,
    devaddr = <<>>,
    heartcount = 0,
    regtype = <<>>,
    head = "xxxxxx0eee",
    len = 0,
    app = <<>>,
    product = <<>>,
    deviceId = <<>>,
    scale = 10,
    temperature = 0,
    env = <<>>,
    dtutype = <<>>,
    hb = 60,
    maxaddr = 0
}).

-define(READ_DISCRETE_INPUTS, 2).
-define(READ_COILS, 1).
-define(WRITE_SINGLE_COIL, 5).
-define(WRITE_MULTIPLE_COILS, 15).
-define(READ_INPUT_REGISTERS, 4).
-define(READ_HOLDING_REGISTERS, 3).
-define(WRITE_SINGLE_HOLDING_REGISTER, 6).
-define(WRITE_MULTIPLE_HOLDING_REGISTERS, 16).

-define(ILLEGAL_FUNCTION, 1).
-define(ILLEGAL_DATA_ADDRESS, 2).
-define(ILLEGAL_DATA_VALUE, 3).
-define(SLAVE_DEVICE_FAILURE, 4).
-define(ACKNOWLEDGE, 5).
-define(SLAVE_DEVICE_BUSY, 6).
-define(NEGATIVE_ACKNOWLEDGE, 7).
-define(MEMORY_PARITY_ERROR, 8).
-define(GATEWAY_PATH_UNAVAILABLE, 10).
-define(GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND, 11).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(FC_READ_COILS, 16#01). %读线圈寄存器
-define(FC_READ_INPUTS, 16#02). %读离散输入寄存器
-define(FC_READ_HREGS, 16#03). %读保持寄存器
-define(FC_READ_IREGS, 16#04). %读输入寄存器

-define(FC_WRITE_COIL, 16#05).  %写单个线圈寄存器
-define(FC_WRITE_HREG, 16#06).  %写单个保持寄存器
-define(FC_WRITE_COILS, 16#0f).  %写多个线圈寄存器
-define(FC_WRITE_HREGS, 16#10).  %写多个保持寄存器

%%_____________________________________________
%%表2 ModBus功能码与数据类型对应表              |
%%|代码 |功能 |数据类型                         |
%%|01   |读   |位                              |
%%|02   |读   |位                              |
%%|03   |读   |整型、字符型、状态字、浮点型      |
%%|04   |读   |整型、状态字、浮点型             |
%%|05   |写   |位                              |
%%|06   |写   |整型、字符型、状态字、浮点型      |
%%|08   |N/A  |重复“回路反馈”信息               |
%%|15   |写   |位                              |
%%|16   |写   |整型、字符型、状态字、浮点型      |
%%——————————————————————————————————————————————

-record(rtu_req, {slaveId, funcode, address, registersnumber, dataByteSize, quality, data}).
-record(rtu_pdu, {slaveId, funcode, dataByteSize, data}).
-record(tcp_request, {sock, tid = 1, address = 1, function, start, data}).

-record(tcp_request1, {
    id,
    tid = 1,
    address = 1,
    function,
    start,
    data,
    env = #{}
}).

%%_________________________________________________________________________________________________________________________________________________________________
%%表1 ModBus功能码
%%_________________________________________________________________________________________________________________________________________________________________
%%|功能码  |  名称                    |  作用
%%|01      |读取线圈状态              |取得一组逻辑线圈的当前状态（ON/OFF)
%%|02      |读取输入状态              |取得一组开关输入的当前状态（ON/OFF)
%%|03      |读取保持寄存器            | 在一个或多个保持寄存器中取得当前的二进制值
%%|04      |读取输入寄存器            | 在一个或多个输入寄存器中取得当前的二进制值
%%|05      |强置单线圈                |强置一个逻辑线圈的通断状态
%%|06      |预置单寄存器              |把具体二进值装入一个保持寄存器
%%|07      |读取异常状态              |取得8个内部线圈的通断状态，这8个线圈的地址由控制器决定，用户逻辑可以将这些线圈定义，以说明从机状态，短报文适宜于迅速读取状态
%%|08      |回送诊断校验              |把诊断校验报文送从机，以对通信处理进行评鉴
%%|09      |编程（只用于484）         |  使主机模拟编程器作用，修改PC从机逻辑
%%|10      |控询（只用于484）         |  可使主机与一台正在执行长程序任务从机通信，探询该从机是否已完成其操作任务，仅在含有功能码9的报文发送后，本功能码才发送
%%|11      |读取事件计数              |可使主机发出单询问，并随即判定操作是否成功，尤其是该命令或其他应答产生通信错误时
%%|12      |读取通信事件记录          |可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成，记录会给出有关错误
%%|13      |编程（184/384 484 584）   |可使主机模拟编程器功能修改PC从机逻辑
%%|14      |探询（184/384 484 584）   |可使主机与正在执行任务的从机通信，定期控询该从机是否已完成其程序操作，仅在含有功能13的报文发送后，本功能码才得发送
%%|15      |强置多线圈                |强置一串连续逻辑线圈的通断
%%|16      |预置多寄存器              |把具体的二进制值装入一串连续的保持寄存器
%%|17      |报告从机标识              |可使主机判断编址从机的类型及该从机运行指示灯的状态
%%|18      |（884和MICRO 84）         |可使主机模拟编程功能，修改PC状态逻辑
%%|19      |重置通信链路              |发生非可修改错误后，是从机复位于已知状态，可重置顺序字节
%%|20      |读取通用参数（584L）       |显示扩展存储器文件中的数据信息
%%|21      |写入通用参数（584L）       |把通用参数写入扩展存储文件，或修改之
%%|22～64  |                          |保留作扩展功能备用
%%|65～72  |保留以备用户功能所用       |留作用户功能的扩展编码
%%|73～119 |非法功能                  |
%%|120～127|  保留                    |留作内部作用
%%|128～255|  保留                    |用于异常应答
%%__________________________________________________________________________________________________________________________________________________________________

%%modbus完整支持很多功能码，但是实际在应用的时候常用的也就那么几个。具体如下：
%%
%%0x01: 读线圈寄存器
%%0x02: 读离散输入寄存器
%%0x03: 读保持寄存器
%%0x04: 读输入寄存器
%%0x05: 写单个线圈寄存器
%%0x06: 写单个保持寄存器
%%0x0f: 写多个线圈寄存器
%%0x10: 写多个保持寄存器
%%如上所示一共8种功能码。这其中有涉及到线圈、离散输入、保持、输入四种寄存器。这名字也不知道谁起的，让人看了一点不通俗易懂，搞得晕晕乎乎。实际上你要是看清他的本质就很简单了。下面分别解释一下：
%%
%%线圈寄存器：实际上就可以类比为开关量，每个bit都对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写，写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。对应上面的功能码也就是：0x01 0x05 0x0f
%%
%%离散输入寄存器：如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式，他也是每个bit表示一个开关量，而他的开关量只能读取输入的开关信号，是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的 0x02
%%
%%保持寄存器：这个寄存器的单位不再是bit而是两个byte，也就是可以存放具体的数据量的，并且是可读写的。比如我我设置时间年月日，不但可以写也可以读出来现在的时间。写也分为单个写和多个写，所以功能码有对应的三个：0x03 0x06 0x10
%%
%%输入寄存器：只剩下这最后一个了，这个和保持寄存器类似，但是也是只支持读而不能写。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04
%%
%%对应的错误返回：
%%在对应功能码基础上加上0x80
%%
%%1、“01”读取线圈状态发送：
%%————————————————
%%版权声明：本文为CSDN博主「JiaoCL」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
%%原文链接：https://blog.csdn.net/liboxiu/article/details/86473516

-define(MODBUS_RTU, <<"MODBUSRTU">>).
-define(MODBUS_TCP, <<"MODBUSTCP">>).
